﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Dominio.Excecoes;

namespace Dominio {
    public class Usuario {
        public virtual long Id { get; set; }
        public virtual string Nome { get; protected set; }
        public virtual string Login { get; protected set; }
        public virtual string Senha { get; protected set; }
        public virtual IList<Categoria> Categorias { get; protected set; }
        public virtual IList<Conta> Contas { get; protected set; }

        protected Usuario(){
            this.Categorias = this.Categorias ?? new List<Categoria>();
            this.Contas = this.Contas ?? new List<Conta>();
        }
        public Usuario(string nome, string login, string senha) : this() {
            this.Nome = nome;
            this.Login = login;
            this.Senha = senha;
        }

        public virtual void ApagaConta(long idConta) {
            var conta = Contas.SingleOrDefault(x => x.Id == idConta);

            if (conta != null)
                Contas.Remove(conta);
        }

        public virtual void ApagaCategoria(long idCategoria) {
            var categoria = Categorias.SingleOrDefault(x => x.Id == idCategoria);
            if (categoria == null)
                throw new NaoEncontrado("Categoria não encontrada!");

            if (categoria.SubCategorias.Count > 0)
                throw new NaoPermitidoException("Existem Sub categorias cadastradas. Excluí-las antes de realizar esta operação.");

            Categorias.Remove(categoria);
        }

        public virtual void ApagaSubCategoria(long idSubCategoria, long idCategoria) {
            var categoria = Categorias.SingleOrDefault(x => x.Id == idCategoria);
            if (categoria == null)
                throw new NaoEncontrado("Categoria não encontrada!");

            categoria.ApagaSub(idSubCategoria);
        }

        public virtual Conta ObtemConta(long id) {
            return Contas.SingleOrDefault(x => x.Id == id);
        }

        public virtual Categoria ObtemCategoria(long id) {
            return Categorias.SingleOrDefault(x => x.Id == id);
        }

        public virtual SubCategoria ObtemSubCategoria(long idSubCategoria, long idCategoria) {
            var categoria = ObtemCategoria(idCategoria);
            if (categoria == null)
                throw new NaoEncontrado("Categoria não encontrada!");
            var sub = categoria.ObtemSub(idSubCategoria);
            if (sub == null)
                throw new NaoEncontrado("Subcategoria não encontrada!");

            return sub;
        }

        public virtual Categoria NovaCategoria(string nome) {
            var categoria = new Categoria(nome, this);

            Categorias.Add(categoria);

            return categoria;
        }

        public virtual SubCategoria NovaCategoria(string nome, long idCategoriaMae) {
            var categoria = Categorias.SingleOrDefault(x => x.Id == idCategoriaMae);

            return categoria.NovaSub(nome);
        }

        public virtual IList<SubCategoria> ObtemSubCategorias(long idCategoria) {
            var categoria = Categorias.SingleOrDefault(x => x.Id == idCategoria);
            if (categoria == null) return null;

            return categoria
                        .SubCategorias
                        .Where(x => x.Categoria.Id == idCategoria)
                        .ToList();
        }

        public virtual Conta NovaConta(string nome) {
            var conta = new Conta(0, nome, this);
            if (Contas.Any(x => x.Nome.Equals(nome))) 
                throw new DuplicadoException("A conta já está cadastrada para o usuário!");

            Contas.Add(conta);

            return conta;
        }
    }
}
